
/*
 * Copyright 2011 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */
#include "SampleCode.h"
#include "SkView.h"
#include "SkCanvas.h"

#include "SkAnimator.h"
#include "SkStream.h"
#include "SkDOM.h"

///////////////////////////////////////////////////////////////////////////////

class SkAnimatorView : public SkView
    {
    public:
        SkAnimatorView();
        virtual ~SkAnimatorView();

        void setURIBase(const char dir[]);

        SkAnimator* getAnimator() const
            {
            return fAnimator;
            }

        bool    decodeFile(const char path[]);
        bool    decodeMemory(const void* buffer, size_t size);
        bool    decodeStream(SkStream* stream);

    protected:
        // overrides
        virtual void onDraw(SkCanvas*);
        virtual bool onQuery(SkEvent* evt);

    private:
        SkString fBaseURI;
        SkAnimator* fAnimator;

        typedef SkView INHERITED;
    };

SkAnimatorView::SkAnimatorView() : fAnimator(NULL) {}

SkAnimatorView::~SkAnimatorView()
    {
    delete fAnimator;
    }

void SkAnimatorView::setURIBase(const char dir[])
    {
    fBaseURI.set(dir);
    }

bool SkAnimatorView::decodeFile(const char path[])
    {
    SkFILEStream* is = new SkFILEStream(path);
    SkAutoUnref aur(is);
    return is->isValid() && this->decodeStream(is);
    }

bool SkAnimatorView::decodeMemory(const void* buffer, size_t size)
    {
    SkMemoryStream* is = new SkMemoryStream(buffer, size);
    SkAutoUnref aur(is);
    return this->decodeStream(is);
    }

static const SkDOMNode* find_nodeID(const SkDOM& dom,
                                    const SkDOMNode* node, const char name[])
    {
    if (NULL == node)
        {
        node = dom.getRootNode();
        }
    do
        {
        const char* idval = dom.findAttr(node, "id");
        if (idval && !strcmp(idval, name))
            {
            return node;
            }
        const SkDOMNode* child = dom.getFirstChild(node);
        if (child)
            {
            const SkDOMNode* found = find_nodeID(dom, child, name);
            if (found)
                {
                return found;
                }
            }
        }
    while ((node = dom.getNextSibling(node)) != NULL);
    return NULL;
    }

bool SkAnimatorView::decodeStream(SkStream* stream)
    {
    delete fAnimator;
    fAnimator = new SkAnimator;
    fAnimator->setURIBase(fBaseURI.c_str());
#if 0
    if (!fAnimator->decodeStream(stream))
        {
        delete fAnimator;
        fAnimator = NULL;
        return false;
        }
#else
    size_t len = stream->getLength();
    char* text = (char*)sk_malloc_throw(len);
    stream->read(text, len);
    SkDOM dom;
    const SkDOM::Node* root = dom.build(text, len);
    if (NULL == root)
        {
        return false;
        }
    if (!fAnimator->decodeDOM(dom, root))
        {
        delete fAnimator;
        fAnimator = NULL;
        return false;
        }
    for (int i = 0; i <= 10; i++)
        {
        SkString name("glyph");
        name.appendS32(i);
        const SkDOM::Node* node = find_nodeID(dom, NULL, name.c_str());
        SkASSERT(node);
        SkRect r;
        dom.findScalar(node, "left", &r.fLeft);
        dom.findScalar(node, "top", &r.fTop);
        dom.findScalar(node, "width", &r.fRight);
        r.fRight += r.fLeft;
        dom.findScalar(node, "height", &r.fBottom);
        r.fBottom += r.fTop;
        SkDebugf("--- %s [%g %g %g %g]\n", name.c_str(),
                 r.fLeft, r.fTop, r.fRight, r.fBottom);
        }
#endif
    return true;
    }

#include "SkTime.h"

void SkAnimatorView::onDraw(SkCanvas* canvas)
    {
    canvas->drawColor(SK_ColorWHITE);
    if (fAnimator)
        {
        fAnimator->draw(canvas, 0);
#if 0
        canvas->save();
        canvas->translate(120, 30);
        canvas->scale(0.5, 0.5);
        fAnimator->draw(canvas, 0);
        canvas->restore();

        canvas->save();
        canvas->translate(190, 40);
        canvas->scale(0.25, 0.25);
        fAnimator->draw(canvas, 0);
        canvas->restore();

        this->inval(NULL);
#endif
        }
    }

bool SkAnimatorView::onQuery(SkEvent* evt)
    {
    if (SampleCode::TitleQ(*evt))
        {
        SampleCode::TitleR(evt, "Animator");
        return true;
        }
    return this->INHERITED::onQuery(evt);
    }

//////////////////////////////////////////////////////////////////////////////

static SkView* MyFactory()
    {
    SkAnimatorView* av = new SkAnimatorView;
//    av->decodeFile("/skimages/test.xml");
#if 0
    av->setURIBase("/skia/trunk/animations/");
    av->decodeFile("/skia/trunk/animations/checkbox.xml");
#else
    av->setURIBase("/");
    av->decodeFile("/testanim.txt");
#endif
    return av;
    }

static SkViewRegister reg(MyFactory);

